home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tricks of the Mac Game Programming Gurus
/
TricksOfTheMacGameProgrammingGurus.iso
/
More Source
/
Pascal
/
OneTest
/
OneEvents.p
< prev
next >
Wrap
Text File
|
1994-10-29
|
7KB
|
228 lines
{YET ANOTHER WAY TO ISOLATE SOME REPETITIVE CODE FROM YOUR ORIGINAL CODE}
{}
{Minimal event loop handling for a program with usually only one window, and one About… selection.}
{The full demo is a very simple skeleton program that is easy to build new programs from.}
{}
{For bigger projects, TransSkel is a lot better, but for VERY small hacks, this saves quite a few kilobytes.}
{(Definitely not worth it if you have some big sounds or picts!) TransSkel, though excellent, lacks a}
{simple starting demo to use for quick hacks, at least one that is both as simple and as complete as}
{the OneTest demo.}
{}
{Though I wholeheartedly recommend TransSkel in the long run, this is not only smaller, but also}
{easier to understand when used as an educational example. With lots of standard code isolated to this}
{file, I believe that the result is more comprehensible than any skeleton program I've seen (e.g. the}
{classic Skel demo).}
{Usage:}
{You plug this unit in between the main program and your window/menu handlers, using the procedures}
{listed below. The big difference between this and "Skel" is that most of the code, in this file, is reuseable}
{and will seldom have to be edited, while Skel is just a demo without isolated reusable code.}
{}
{One idea when making the stubs was that it should be pretty easy to plug in TransSkel, once a program gets}
{complicated enough to justify it.}
{Your unit StdHandlers should include the following:}
{}
{procedure DoUpdate(w: WindowPtr);}
{procedure DoClose(w:WindowPtr);}
{procedure DoAbout;}
{procedure DoMenu(menuID, item: integer);}
{procedure DoMouse(where: Point; mods: longint);}
{procedure DoKey(theChar: char; mods: longint);}
{… and you should call OneInit during startup.}
{}
{The flag gDone should be set to true when you want the program to quit. The global gHasCQD is}
{initialized by a call to SysEnvirons during program startup, and should be used to check if Color}
{QD is available.}
{Based on code from OutOfThisGWorld; it was pretty short. One of the conclusions: It is hard to get under}
{2k with a program that uses windows and menus.}
unit OneEvents;
interface
uses
{$ifc undefined THINK_PASCAL}
Types, QuickDraw, Events, Windows, Dialogs, Fonts, DiskInit, TextEdit, Traps, Desk, {}
Memory, SegLoad, Scrap, ToolUtils, OSEvents, OSUtils, Menus, Resources, StandardFile,{}
GestaltEqu, Files, Errors, {}
{$endc}
StdHandlerStubs;
procedure OneInit (aboutStr: Str255);
procedure PollEvents;
implementation
const
kSleep = 0;
appleID = 1;
var
gWNEImplemented: Boolean;
procedure OneInit (aboutStr: Str255);
var
appleMenu: MenuHandle;
begin
{$ifc undefined THINK_PASCAL}
{ Initialize all the needed managers. }
InitGraf(@qd.thePort);
InitFonts;
InitWindows;
InitMenus;
TEInit;
InitDialogs(nil);
MaxApplZone;
{$endc}
appleMenu := NewMenu(appleID, char(20)); {Apple menu symbol}
InsertMenu(appleMenu, 0);
if length(aboutStr) > 0 then
begin
AppendMenu(appleMenu, aboutStr);
AppendMenu(appleMenu, '(-');
end;
AddResMenu(appleMenu, 'DRVR');
{Main program should call DrawMenuBar once it's done setting up its own menus.}
{Check for WNE being implemented, save in a boolean. This improves compatibility}
{with (very) old system versions.}
gWNEImplemented := NGetTrapAddress($A860, ToolTrap) <> NGetTrapAddress($A89F, ToolTrap);
{Check for Color QD being available. (AA1E is GetCIcon, i.e. any CQD routine.)}
gHasCQD := NGetTrapAddress($AA1E, toolTrap) <> NGetTrapAddress($A89F, toolTrap);{_Unimplemented}
InitCursor;
end;
procedure HandleMenu (mSelect: LongInt);
var
menuID: Integer;
menuItem: Integer;
savePort: GrafPtr;
name: Str255;
ignore: integer;
begin
menuID := HiWord(mSelect);
menuItem := LoWord(mSelect);
if menuID = appleID then
if menuItem = 1 then
DoAbout
else
begin
GetPort(savePort);
GetItem(GetMHandle(appleID), menuItem, name);
ignore := OpenDeskAcc(name);
SetPort(savePort);
end
else if menuID <> 0 then {Zero when no menu?}
DoMenu(menuID, menuItem);
HiliteMenu(0);
end;
procedure PollEvents;
var
anEvent: EventRecord;
theWindow: WindowPtr;
clickArea: Integer;
screenRect: Rect;
savePort: GrafPtr;
hasEvent: Boolean;
growR: Rect;
growRes: Longint;
begin
if gWNEImplemented then
hasEvent := WaitNextEvent(everyEvent, anEvent, kSleep, nil)
else
begin
SystemTask; (* Handle desk accessories *)
hasEvent := GetNextEvent(everyEvent, anEvent);
end;
if hasEvent then
case anEvent.what of
mouseDown:
begin
clickArea := FindWindow(anEvent.where, theWindow);
if clickArea = inDrag then
begin
screenRect := GetGrayRgn^^.rgnBBox;
DragWindow(theWindow, anEvent.where, screenRect);
end
else if clickArea = inGoAway then
begin
if TrackGoAway(theWindow, anEvent.where) then
DoClose(theWindow);
end
else if clickArea = inMenuBar then
begin
HandleMenu(MenuSelect(anEvent.where));
end
else if clickArea = inContent then
begin
if theWindow <> FrontWindow then
SelectWindow(theWindow)
else
DoMouse(anEvent.where, anEvent.modifiers);
end
else if clickArea = inGrow then
begin
growR := GetGrayRgn^^.rgnBBox;
InsetRect(growR, 10, 10); {Wrong rect???}
growRes := GrowWindow(theWindow, anEvent.where, growR);
if growRes <> 0 then
begin
SizeWindow(theWindow, LoWord(growRes), HiWord(growRes), false);
GetPort(savePort);
SetPort(theWindow);
InvalRect(theWindow^.portRect);
SetPort(savePort);
end;
end;
end; {mouseDown}
updateEvt:
begin
theWindow := WindowPtr(anEvent.message);
GetPort(savePort);
SetPort(theWindow);
BeginUpdate(theWindow);
DoUpdate(theWindow);
EndUpdate(theWindow);
SetPort(savePort);
end; {updateEvt}
keyDown, autoKey:
begin
if BitAnd(anEvent.modifiers, cmdKey) <> 0 then
HandleMenu(MenuKey(Char(BitAnd(anEvent.message, charCodeMask))))
else
DoKey(Char(BitAnd(anEvent.message, charCodeMask)), anEvent.modifiers);
end; {key}
{activateEvt: }
{begin}
{What's appropriate here? Yet another stub, DoActivate?}
{end;}
{And more: suspend/resume, Apple Events… but a many simple programs can live without them.}
{Real programs must handle bad disk insertion too!}
diskEvt: {Handle uninitialized disks}
if (HiWord(anEvent.message) <> noErr) then
begin
DILoad;
if DIBadMount(Point($00800080), anEvent.message) <> noErr then
;
DIUnload;
end;{diskEvt, if}
otherwise
end; {case}
end; {PollEvent}
end.